package vip.xiaonuo.biz.modular.dict.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import vip.xiaonuo.biz.modular.dict.controller.HikController;
import vip.xiaonuo.biz.modular.dict.entity.HbArea;
import vip.xiaonuo.biz.modular.dict.entity.HbCamera;
import vip.xiaonuo.biz.modular.dict.entity.HbPlayGroup;
import vip.xiaonuo.biz.modular.dict.entity.HbPlayGroupCamera;
import vip.xiaonuo.biz.modular.dict.mapper.HbAreaMapper;
import vip.xiaonuo.biz.modular.dict.mapper.HbCameraMapper;
import vip.xiaonuo.biz.modular.dict.mapper.HbPlayGroupCameraMapper;
import vip.xiaonuo.biz.modular.dict.mapper.HbPlayGroupMapper;
import vip.xiaonuo.biz.modular.dict.service.IHikService;
import vip.xiaonuo.common.cache.CommonCacheOperator;
import vip.xiaonuo.common.hikservice.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 张奇
 * @desc
 * @time 2024/3/4 10:31
 */
@Service
public class HikServiceImpl implements IHikService {

    @Resource
    private HikUtil hikUtil;

    @Resource
    private CommonCacheOperator commonCacheOperator;

    @Resource
    private HbPlayGroupMapper hbPlayGroupMapper;

    @Resource
    private HbPlayGroupCameraMapper hbPlayGroupCameraMapper;

    @Resource
    private HbAreaMapper hbAreaMapper;

    @Resource
    private HbCameraMapper hbCameraMapper;

    /**
     * 查询摄像头资源
     *
     * @param resourcePageVo 查询参数
     * @return
     */
    @Override
    public HikDto.HikCameraPageDto listCamera(HikVo.ResourcePageVo resourcePageVo) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.RESOURCE_LIST, JSONUtil.toJsonStr(resourcePageVo));
        HikResponseDto<HikDto.HikCameraPageDto> hikResponseDto = HikResponseDto.ofHikCameraPageList(jsonObject);
        return hikResponseDto.getData();
    }


    /**
     * 获取摄像头流地址
     *
     * @param cameraUrlVo
     * @return
     */
    @Override
    public HikDto.CameraUrlDto getCameraUrl(HikVo.CameraUrlVo cameraUrlVo) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.RESOURCE_URL, JSONUtil.toJsonStr(cameraUrlVo));
        HikResponseDto<HikDto.CameraUrlDto> hikResponseDto = HikResponseDto.ofHikCameraUrl(jsonObject);
        return hikResponseDto.getData();
    }

    /**
     * 同步摄像头在线状态
     */
    @Override
    public void syncCameraLineStatus() {
        List<HbArea> hbAreas = hbAreaMapper.selectList(null);
        for (HbArea hbArea : hbAreas) {
            // 同步区域下的摄像头在线状态
            QueryWrapper<HbCamera> objectQueryWrapper = new QueryWrapper<>();
            objectQueryWrapper.eq("area_code", hbArea.getAreaCode());
            List<HbCamera> hbCameras = hbCameraMapper.selectList(objectQueryWrapper);
            Integer totalCamera = hbCameras.size();
            Integer onLine = 0;
            Integer offLine = 0;
            HikVo.ResourceLineVo resourceLineVo = new HikVo.ResourceLineVo();
            for (HbCamera hbCamera : hbCameras) {
                resourceLineVo.setIndexCode(new String[]{hbCamera.getIndexCode()});
                JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.RESOURCE_ONLINE, JSONUtil.toJsonStr(resourceLineVo));
                HikResponseDto<HikDto.HikCameraLinePageDto> hikResponseDto = HikResponseDto.ofHikCameraLinePageList(jsonObject);
                //在线状态
                if (hikResponseDto.getData().getList() == null || hikResponseDto.getData().getList().size() == 0) {
                    offLine += 1;
                } else {
                    HikDto.CameraLineDto cameraLineDto = hikResponseDto.getData().getList().get(0);
                    if (cameraLineDto.getOnline() == 1) {
                        onLine += 1;
                    } else {
                        offLine += 1;
                    }
                }
            }
            //    缓存在线离线信息
            commonCacheOperator.put("camera:online:" + hbArea.getAreaCode(), JSONUtil.toJsonStr(MapUtil.builder()
                    .put("totalCamera", totalCamera)
                    .put("onLine", onLine)
                    .put("offLine", offLine)
                    .build()));
        }
    }

    /**
     * 获取摄像头的在线离线状态
     *
     * @return
     */
    @Override
    public JSONObject getCameraLineCount() {
        Object o = commonCacheOperator.get("camera:online");
        JSONObject jsonObject = JSONUtil.parseObj(o);
        if (jsonObject.getInt("totalCamera") == 0) {
            syncCamera();
            o = commonCacheOperator.get("camera:online");
            jsonObject = JSONUtil.parseObj(o);
        }
        return jsonObject;
    }

    /**
     * 云台控制
     *
     * @param cameraController
     * @return
     */
    @Override
    public Boolean controlCamera(HikVo.CameraController cameraController) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.CAMERA_CONTROL, JSONUtil.toJsonStr(cameraController));
        HikResponseDto<Boolean> hikResponseDto = HikResponseDto.ofHikControl(jsonObject);
        return hikResponseDto.getData();
    }


    /**
     * 回放地址
     *
     * @param cameraBackPlay
     * @return
     */
    @Override
    public HikDto.CameraBackPlayDto getBackPlay(HikVo.CameraBackPlay cameraBackPlay) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.CAMERA_BACK_PLAY, JSONUtil.toJsonStr(cameraBackPlay));
        HikResponseDto<HikDto.CameraBackPlayDto> hikResponseDto = HikResponseDto.ofHikBackPlay(jsonObject);
        return hikResponseDto.getData();
    }


    /**
     * 抓图
     *
     * @param cameraCatch
     * @return
     */
    @Override
    public String cameraCatch(HikVo.CameraCatch cameraCatch) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.CAMERA_CATCH, JSONUtil.toJsonStr(cameraCatch));
        HikResponseDto<String> hikResponseDto = HikResponseDto.ofHikPic(jsonObject);
        return hikResponseDto.getData();
    }

    /**
     * 开始录像
     *
     * @param cameraVideoStart
     * @return
     */
    @Override
    public String cameraVideoStart(HikVo.CameraVideoStart cameraVideoStart) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.CAMERA_VIDEO_START, JSONUtil.toJsonStr(cameraVideoStart));
        HikResponseDto<String> hikResponseDto = HikResponseDto.ofHikVideo(jsonObject);
        return hikResponseDto.getData();
    }

    /**
     * 停止录像
     *
     * @param cameraVideoStop
     * @return
     */
    @Override
    public Boolean cameraVideoStop(HikVo.CameraVideoStop cameraVideoStop) {
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.CAMERA_VIDEO_END, JSONUtil.toJsonStr(cameraVideoStop));
        HikResponseDto<Boolean> hikResponseDto = HikResponseDto.ofHikControl(jsonObject);
        return hikResponseDto.getData();
    }


    /**
     * 新增播放分组
     *
     * @param hbPlayGroup
     * @return
     */
    @Override
    public Boolean addCameraPlayGroup(HbPlayGroup hbPlayGroup) {
        hbPlayGroupMapper.insertSelective(hbPlayGroup);
        return true;

    }

    /**
     * 删除播放分组
     *
     * @param id
     * @return
     */
    @Override
    public Boolean removeCameraPlayGroup(Long id) {
        hbPlayGroupMapper.deleteById(id);
        return true;
    }

    /**
     * 更新播放分组
     *
     * @param hbPlayGroup
     * @return
     */
    @Override
    public Boolean updateCameraPlayGroup(HbPlayGroup hbPlayGroup) {
        hbPlayGroupMapper.updateByPrimaryKeySelective(hbPlayGroup);
        return true;
    }

    /**
     * 新增摄像头的播放分组
     *
     * @return
     */
    @Override
    public Boolean addCameraPlayGroupCamera(HikController.GroupCameraRelVo groupCameraRelVo) {
        for (String s : groupCameraRelVo.getCameraId().split(",")) {
            hbPlayGroupCameraMapper.insertSelective(HbPlayGroupCamera.builder()
                    .playGroupId(groupCameraRelVo.getParentId())
                    .cameraId(Long.parseLong(s))
                    .build());
        }


        return true;
    }

    /**
     * 删除摄像头的播放分组
     *
     * @param id
     * @return
     */
    @Override
    public Boolean removeCameraPlayGroupCamera(Long id) {
        hbPlayGroupCameraMapper.deleteById(id);
        return true;
    }

    /**
     * 更新摄像头的播放分组
     *
     * @param hbPlayGroupCamera
     * @return
     */
    @Override
    public Boolean updateCameraPlayGroupCamera(HbPlayGroupCamera hbPlayGroupCamera) {
        hbPlayGroupCameraMapper.updateByPrimaryKeySelective(hbPlayGroupCamera);
        return true;
    }

    /**
     * 查询
     */
    @Override
    public Map<String, Object> getLocalCameraList(String name) {

        List<Map<String, Object>> maps1 = hbAreaMapper.selectAll();
        for (Map<String, Object> stringObjectMap : maps1) {
            String areaCode = MapUtil.getStr(stringObjectMap, "areaCode");
            List<Map<String, Object>> maps = hbCameraMapper.selectByAreaCode(areaCode, name);
            stringObjectMap.put("children", maps);
        }
        return MapUtil.builder(new HashMap<String, Object>())
                .put("areaName", "河北公司")
                .put("areaCode", "root000000")
                .put("children", maps1)
                .put("id", 1)
                .build();

    }

    /**
     * 查询所有的摄像头
     *
     * @return
     */
    @Override
    public List<HbCamera> getAllCamera(String name) {
        QueryWrapper<HbCamera> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", name);
        List<HbCamera> hbCameras = hbCameraMapper.selectList(queryWrapper);
        return hbCameras;
    }

    /**
     * 查询轮巡分组摄像头信息
     *
     * @param name
     * @return
     */
    @Override
    public Map<String, Object> getPlayCameraList(String name) {

        List<Map<String, Object>> maps1 = hbPlayGroupMapper.selectByParent(1L);

        List<Map<String, Object>> oneMap = new ArrayList<>();

        //二级分组
        for (Map<String, Object> stringObjectMap : maps1) {
            Map<String, Object> muluMap = new HashMap<>();
            muluMap.put("id", MapUtil.getStr(stringObjectMap, "id"));
            muluMap.put("groupName", MapUtil.getStr(stringObjectMap, "groupName"));
            muluMap.put("type", "1");
            muluMap.put("groupCameraId", MapUtil.getStr(stringObjectMap, "id"));

            //查询二级分组是否包含摄像头
            Long areaId = MapUtil.getLong(stringObjectMap, "id");
            List<Map<String, Object>> firstCameraList = hbCameraMapper.selectByGroupId(areaId, name);
            oneMap.add(muluMap);


            //stringObjectMap.put("cameraList", firstCameraList);
            //查询二级分组是否有下一级
            List<Map<String, Object>> maps2 = hbPlayGroupMapper.selectByParent(areaId);
            List<Map<String, Object>> twoMap = new ArrayList<>();
            for (Map<String, Object> objectMap : maps2) {

                Map<String, Object> muluMap2 = new HashMap<>();
                muluMap2.put("id", MapUtil.getStr(objectMap, "id"));
                muluMap2.put("groupName", MapUtil.getStr(objectMap, "groupName"));
                muluMap2.put("type", "1");
                muluMap2.put("groupCameraId", MapUtil.getStr(objectMap, "id"));
                twoMap.add(muluMap2);
                Long secondAreaId = MapUtil.getLong(objectMap, "id");
                List<Map<String, Object>> secondCameraList = hbCameraMapper.selectByGroupId(secondAreaId, name);

                //objectMap.put("cameraList", secondCameraList);
                //判断是否有三级
                List<Map<String, Object>> maps3 = hbPlayGroupMapper.selectByParent(secondAreaId);
                List<Map<String, Object>> threeMap = new ArrayList<>();
                for (Map<String, Object> map : maps3) {
                    Map<String, Object> muluMap3 = new HashMap<>();
                    muluMap3.put("id", MapUtil.getStr(map, "id"));
                    muluMap3.put("groupName", MapUtil.getStr(map, "groupName"));
                    muluMap3.put("type", "1");
                    muluMap3.put("groupCameraId", MapUtil.getStr(map, "id"));
                    threeMap.add(muluMap3);
                    Long thirdAreaId = MapUtil.getLong(map, "id");
                    List<Map<String, Object>> thirdCameraList = hbCameraMapper.selectByGroupId(thirdAreaId, name);
                    for (Map<String, Object> map1 : thirdCameraList) {
                        Map<String, Object> muluMap1 = new HashMap<>();
                        muluMap1.put("id", MapUtil.getStr(map1, "indexCode"));
                        muluMap1.put("groupName", MapUtil.getStr(map1, "groupName"));
                        muluMap1.put("type", "2");
                        muluMap1.put("groupCameraId", MapUtil.getInt(map1, "groupCameraId"));
                        muluMap1.put("children", new ArrayList<>());
                        threeMap.add(muluMap1);
                    }
                }
                for (Map<String, Object> map : secondCameraList) {
                    Map<String, Object> muluMap1 = new HashMap<>();
                    muluMap1.put("id", MapUtil.getStr(map, "indexCode"));
                    muluMap1.put("groupName", MapUtil.getStr(map, "groupName"));
                    muluMap1.put("type", "2");
                    muluMap1.put("groupCameraId", MapUtil.getInt(map, "groupCameraId"));
                    muluMap1.put("children", new ArrayList<>());
                    threeMap.add(muluMap1);
                }
                muluMap2.put("children", threeMap);
            }
            for (Map<String, Object> firstCameraMap : firstCameraList) {
                Map<String, Object> muluMap1 = new HashMap<>();
                muluMap1.put("id", MapUtil.getStr(firstCameraMap, "indexCode"));
                muluMap1.put("groupName", MapUtil.getStr(firstCameraMap, "groupName"));
                muluMap1.put("groupCameraId", MapUtil.getInt(firstCameraMap, "groupCameraId"));
                muluMap1.put("type", "2");
                muluMap1.put("children", new ArrayList<>());
                twoMap.add(muluMap1);
            }
            muluMap.put("children", twoMap);
        }
        return MapUtil.builder(new HashMap<String, Object>())
                .put("children", oneMap)
                .put("id", 1)
                .put("groupName", "全部")
                .put("parentId", "0")
                .build();
    }

    /**
     * 同步区域
     */
    @Override
    public void syncArea() {
        HikVo.AreaLinkVo areaLinkVo = new HikVo.AreaLinkVo();
        areaLinkVo.setPageNo(1);
        areaLinkVo.setPageSize(1000);
        areaLinkVo.setParentIndexCode("root000000");
        areaLinkVo.setResourceType("region");
        areaLinkVo.setCascadeFlag(0);
        JSONObject jsonObject = hikUtil.sendMsg(HikUrlEnum.CHILD_AREA_LIST, JSONUtil.toJsonStr(areaLinkVo));
        HikResponseDto<HikDto.HikAreaPageDto> hikResponseDto = HikResponseDto.ofHikAreaPageList(jsonObject);
        List<HikDto.HikAreaDto> hikAreaDtos = hikResponseDto.getData().getList();
        for (HikDto.HikAreaDto hikAreaDto : hikAreaDtos) {
            HbArea hbArea = hbAreaMapper.selectByAreaCode(hikAreaDto.getIndexCode());
            if (hbArea == null) {
                //不存在新增
                hbAreaMapper.insertSelective(HbArea.builder()
                        .areaCode(hikAreaDto.getIndexCode())
                        .areaName(hikAreaDto.getName())
                        .parentCode(hikAreaDto.getParentIndexCode())
                        .parentName("河北公司")
                        .sort(hikAreaDto.getSort())
                        .build());
            } else {
                //存在修改
                if (!hikAreaDto.getName().equals(hbArea.getAreaName())) {
                    hbAreaMapper.updateByPrimaryKeySelective(HbArea.builder()
                            .id(hbArea.getId())
                            .areaName(hikAreaDto.getName())
                            .sort(hikAreaDto.getSort())
                            .build());
                }
            }
        }
    }

    /**
     * 同步摄像机
     */
    @Override
    public void syncCamera() {
        List<HbArea> hbAreas = hbAreaMapper.selectList(null);
        for (HbArea hbArea : hbAreas) {
            HikVo.ResourcePageVo resourcePageVo = new HikVo.ResourcePageVo();
            resourcePageVo.setResourceType("camera");
            resourcePageVo.setPageNo(1);
            resourcePageVo.setPageSize(1000);
            resourcePageVo.setRegionIndexCodes(new String[]{hbArea.getAreaCode()});
            HikDto.HikCameraPageDto hikCameraPageDto = listCamera(resourcePageVo);
            List<HikDto.CameraDto> list = hikCameraPageDto.getList();
            for (HikDto.CameraDto cameraDto : list) {
                HbCamera hbCamera = hbCameraMapper.selectByIndexCode(cameraDto.getIndexCode());
                if (hbCamera == null) {
                    hbCameraMapper.insertSelective(HbCamera.builder()
                            .indexCode(cameraDto.getIndexCode())
                            .name(cameraDto.getName())
                            .areaCode(hbArea.getAreaCode())
                            .areaName(hbArea.getAreaName())
                            .parentCode(hbArea.getParentCode())
                            .parentName(hbArea.getParentName())
                            .cameraType(cameraDto.getCameraType())
                            .rtspUrl("")
                            .wsUrl("")
                            .build());
                } else {
                    //存在修改摄像头
                    if (!hbCamera.getName().equals(cameraDto.getName())) {
                        hbCameraMapper.updateByPrimaryKeySelective(HbCamera.builder()
                                .id(hbCamera.getId())
                                .name(cameraDto.getName())
                                .build());
                    }
                }
            }
        }
    }

    /**
     * 获取所有的轮巡组
     *
     * @return
     */
    @Override
    public List<HbPlayGroup> getHomeCameraList() {
        QueryWrapper<HbPlayGroup> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.gt("parent_id", 0);
        List<HbPlayGroup> hbPlayGroups = hbPlayGroupMapper.selectList(objectQueryWrapper);
        return hbPlayGroups;
    }

    /**
     * @param groupId 分组ID
     * @return
     */
    @Override
    public List<String> getHomeCameraListMap(Long groupId) {
        List<String> maps = hbPlayGroupMapper.selectByGroupId(groupId);
        return maps;
    }
}
